home *** CD-ROM | disk | FTP | other *** search
Text File | 1985-09-14 | 77.0 KB | 3,147 lines |
- >>> STDIO.H 387
- /*
- ** STDIO.H -- Standard Small-C Definitions
- **
- ** Copyright 1983 L. E. Payne and J. E. Hendrix
- */
- #define stdin 0
- #define stdout 1
- #define stderr 2
- #define stdaux 3
- #define stdprn 4
- #define ERR (-2)
- #define EOF (-1)
- #define YES 1
- #define NO 0
- #define NULL 0
- #define CR 13
- #define LF 10
- #define BELL 7
- #define SPACE ' '
- #define NEWLINE LF
-
- >>> NOTICE.H 124
- #define VERSION "Small-C Compiler, Version 2.1, (Rev. 70)\n"
- #define CRIGHT1 "Copyright 1982, 1983, 1985 J. E. Hendrix\n\n"
- >>> CC.DEF 5310
- /*
- ** CC.DEF -- Symbol Definitions for Small-C compiler.
- */
-
- /*
- ** compile options
- */
- #define NOCCARGC /* no argument counts */
- #define SEPARATE /* compile separately */
- #define OPTIMIZE /* compile output optimizer */
- #define DYNAMIC /* allocate memory dynamically */
- #define COL /* terminate labels with a colon */
- /* #define UPPER /* force symbols to upper case */
- #define LINK /* will use with linking loader */
-
- /*
- ** machine dependent parameters
- */
- #define BPW 2 /* bytes per word */
- #define LBPW 1 /* log2(BPW) */
- #define SBPC 1 /* stack bytes per character */
- #define ERRCODE 7 /* op sys return code */
-
- /*
- ** symbol table format
- */
- #define IDENT 0
- #define TYPE 1
- #define CLASS 2
- #define OFFSET 3
- #define NAME 5
- #define OFFSIZE (NAME-OFFSET)
- #define SYMAVG 10
- #define SYMMAX 14
-
- /*
- ** symbol table parameters
- */
- #define NUMLOCS 25
- #define STARTLOC symtab
- #define ENDLOC (symtab+NUMLOCS*SYMAVG)
- #define NUMGLBS 200
- #define STARTGLB ENDLOC
- #define ENDGLB (ENDLOC+(NUMGLBS-1)*SYMMAX)
- #define SYMTBSZ 3050 /* (NUMLOCS*SYMAVG + NUMGLBS*SYMMAX) */
-
- /*
- ** System wide name size (for symbols)
- */
- #define NAMESIZE 9
- #define NAMEMAX 8
-
- /*
- ** possible entries for "IDENT"
- */
- #define LABEL 0
- #define VARIABLE 1
- #define ARRAY 2
- #define POINTER 3
- #define FUNCTION 4
-
- /*
- ** possible entries for "TYPE"
- ** low order 2 bits make type unique within length
- ** high order bits give length of object
- */
- /* LABEL 0 */
- #define CCHAR (1<<2)
- #define CINT (BPW<<2)
-
- /*
- ** possible entries for "CLASS"
- */
- /* LABEL 0 */
- #define STATIC 1
- #define AUTOMATIC 2
- #define EXTERNAL 3
- #define AUTOEXT 4
- #define GLOBAL 5
-
- /*
- ** segment types
- */
- #define DATASEG 1
- #define CODESEG 2
-
- /*
- ** "switch" table
- */
- #define SWSIZ (2*BPW)
- #define SWTABSZ (90*SWSIZ)
-
- /*
- ** "while" statement queue
- */
- #define WQTABSZ 30
- #define WQSIZ 3
- #define WQMAX (wq+WQTABSZ-WQSIZ)
-
- /*
- ** entry offsets in while queue
- */
- #define WQSP 0
- #define WQLOOP 1
- #define WQEXIT 2
-
- /*
- ** literal pool
- */
- #define LITABSZ 1500
- #define LITMAX (LITABSZ-1)
-
- /*
- ** input line
- */
- #define LINEMAX 127
- #define LINESIZE 128
-
- /*
- ** entries in staging buffer
- */
- #define STAGESIZE 200
-
- /*
- ** macro (define) pool
- */
- #define MACNBR 300
- #define MACNSIZE (MACNBR*(NAMESIZE+2))
- #define MACNEND (macn+MACNSIZE)
- #define MACQSIZE (MACNBR*7)
- #define MACMAX (MACQSIZE-1)
-
- /*
- ** statement types
- */
- #define STIF 1
- #define STWHILE 2
- #define STRETURN 3
- #define STBREAK 4
- #define STCONT 5
- #define STASM 6
- #define STEXPR 7
- #define STDO 8 /* compile "do" logic */
- #define STFOR 9 /* compile "for" logic */
- #define STSWITCH 10 /* compile "switch/case/default" logic */
- #define STCASE 11
- #define STDEF 12
- #define STGOTO 13 /* compile "goto" logic */
- #define STLABEL 14
-
- /*
- ** compiler-generated p-codes
- */
- #define _LABEL 0
- #define _RLAB 1
- #define _GCHAR 2
- #define _GINT 3
- #define _LINT 4
- #define _LCHAR 5
- #define _GSTK 6
- #define _SCHAR 7
- #define _SINT 8
- #define _PINT 9
- #define _PCHAR 10
- #define _MOVE 11
- #define _SWAP 12
- #define _OFFSET 13
- #define _STRING 14
- #define _IMMED 15
- #define _IMMED2 16
- #define _PUSH 17
- #define _POP 18
- #define _SWAPSTK 19
- #define _SW 20
- #define _CALL 21
- #define _FUNC 22
- #define _RET 23
- #define _CALLSTK 24
- #define _JUMP 25
- #define _TESTJUMP 26
- #define _DEFBYTE 27
- #define _DEFWORD 28
- #define _DEFLABEL 29
- #define _MODSTK 30
- #define _DBL 31
- #define _DBL2 32
- #define _ADD 33
- #define _SUB 34
- #define _MULT 35
- #define _DIV 36
- #define _MOD 37
- #define _OR 38
- #define _XOR 39
- #define _AND 40
- #define _LNEG 41
- #define _ASR 42
- #define _ASL 43
- #define _NEG 44
- #define _COM 45
- #define _INC 46
- #define _DEC 47
- #define _EQ 48
- #define _EQ0 49
- #define _NE 50
- #define _NE0 51
- #define _LT 52
- #define _LT0 53
- #define _LE 54
- #define _LE0 55
- #define _GT 56
- #define _GT0 57
- #define _GE 58
- #define _GE0 59
- #define _ULT 60
- #define _ULT0 61
- #define _ULE 62
- #define _UGT 63
- #define _UGE 64
- #define _COUNT 65
- #define _DB 66
- #define _DBZERO 67
- #define _DW 68
- #define _DWZERO 69
-
- /*
- ** optimizer-generated p-codes
- */
- #define _ANY -1
- #define _FINT 100 /* fetch local int */
- #define _FCHAR 101 /* fetch local char */
- #define _GLIO 102 /* get local int with offset */
- #define _GLCO 103 /* get local char with offset */
- #define _GGIO1 104 /* get global int with offset */
- #define _GGIO2 105 /* continuation of _GGIO1 */
- #define _GGCO1 106 /* get global char with offset */
- #define _GGCO2 107 /* continuation OF _GGCO1 */
- #define _ADDI 108 /* add immediate */
- #define _SUBI 109 /* subtract immediate */
- #define _INT_I 110 /* indirect integer post incr */
- #define _INT_D 111 /* indirect integer post decr */
- #define _CHAR_I 112 /* indirect character post incr */
- #define _CHAR_D 113 /* indirect character post decr */
- #define _XXX_I1 114 /* direct int/char post incr */
- #define _XXX_D1 115 /* direct int/char post decr */
- #define _XXX_X2 116 /* continue _XXX_I1 and _XXX_D1 */
-
- >>> CC1.C 3548
- /*
- ** Small-C Compiler Part 1
- */
- #include <stdio.h>
- #include "notice.h"
- #include "cc.def"
-
- /*
- ** miscellaneous storage
- */
- int
- #ifdef STGOTO
- nogo, /* > 0 disables goto statements */
- noloc, /* > 0 disables block locals */
- #endif
- op[16], /* function addresses of binary operators */
- op2[16], /* same for unsigned operators */
- opindex, /* index to matched operator */
- opsize, /* size of operator in bytes */
- swactive, /* true inside a switch */
- swdefault,/* default label #, else 0 */
- *swnext, /* address of next entry */
- *swend, /* address of last table entry */
- #ifdef DYNAMIC
- *stage, /* output staging buffer */
- *wq, /* while queue */
- #else
- stage[STAGESIZE*2],
- wq[WQTABSZ],
- #endif
- argcs, /* static argc */
- *argvs, /* static argv */
- *wqptr, /* ptr to next entry */
- litptr, /* ptr to next entry */
- macptr, /* macro buffer index */
- pptr, /* ptr to parsing buffer */
- oper, /* address of binary operator function */
- ch, /* current character of line being scanned */
- nch, /* next character of line being scanned */
- declared, /* # of local bytes declared, else -1 when done */
- iflevel, /* #if... nest level */
- skiplevel,/* level at which #if... skipping started */
- func1, /* true for first function */
- nxtlab, /* next avail label # */
- litlab, /* label # assigned to literal pool */
- beglab, /* beginning label -- first function */
- csp, /* compiler relative stk ptr */
- argstk, /* function arg sp */
- argtop,
- ncmp, /* # open compound statements */
- errflag, /* non-zero after 1st error in statement */
- eof, /* set non-zero on final input eof */
- input, /* fd # for input file */
- input2, /* fd # for "include" file */
- output, /* fd # for output file */
- files, /* non-zero if file list specified on cmd line */
- filearg, /* cur file arg index */
- glbflag, /* non-zero if internal globals */
- ctext, /* non-zero to intermix c-source */
- ccode, /* non-zero while parsing c-code */
- /* zero when passing assembly code */
- *stagenext,/* next addr in stage */
- *stagetail,/* last addr of data in stage */
- *stagelast,/* last addr in stage */
- listfp, /* file pointer to list device */
- lastst, /* last executed statement type */
- *iptr, /* work ptr to any int buffer */
- oldseg; /* current segment, 0, DATASEG, CODESEG */
-
- char
- #ifdef OPTIMIZE
- optimize, /* optimize output of staging buffer */
- #endif
- alarm, /* audible alarm on errors? */
- monitor, /* monitor function headers? */
- pause, /* pause for operator on errors? */
- #ifdef DYNAMIC
- *symtab, /* symbol table */
- *litq, /* literal pool */
- *macn, /* macro name buffer */
- *macq, /* macro string buffer */
- *pline, /* parsing buffer */
- *mline, /* macro buffer */
- #else
- symtab[SYMTBSZ],
- litq[LITABSZ],
- macn[MACNSIZE],
- macq[MACQSIZE],
- pline[LINESIZE],
- mline[LINESIZE],
- swq[SWTABSZ],
- #endif
- *line, /* points to pline or mline */
- *lptr, /* ptr to either */
- *glbptr, /* ptrs to next entries */
- *locptr, /* ptr to next local symbol */
- quote[2], /* literal string for '"' */
- *cptr, /* work ptrs to any char buffer */
- *cptr2,
- *cptr3,
- msname[NAMESIZE], /* macro symbol name array */
- ssname[NAMESIZE]; /* static symbol name array */
-
- #include "cc11.c"
- #include "cc12.c"
- #include "cc13.c"
-
- #ifndef SEPARATE
- #include "cc21.c"
- #include "cc22.c"
- #include "cc31.c"
- #include "cc32.c"
- #include "cc33.c"
- #include "cc41.c"
- #include "cc42.c"
- #endif
-
- >>> CC11.C 5513
- /*
- ** execution begins here
- */
- main(argc, argv) int argc, *argv; {
- fputs(VERSION, stderr);
- fputs(CRIGHT1, stderr);
- argcs=argc;
- argvs=argv;
- #ifdef DYNAMIC
- swnext=calloc(SWTABSZ, 1);
- swend=swnext+((SWTABSZ-SWSIZ)>>1);
- stage=calloc(STAGESIZE, 2*BPW);
- wq=calloc(WQTABSZ, BPW);
- litq=calloc(LITABSZ, 1);
- macn=calloc(MACNSIZE, 1);
- macq=calloc(MACQSIZE, 1);
- pline=calloc(LINESIZE, 1);
- mline=calloc(LINESIZE, 1);
- #else
- swend=(swnext=swq)+SWTABSZ-SWSIZ;
- #endif
- stagelast=stage+(STAGESIZE*2*BPW);
- swactive= /* not in switch */
- stagenext= /* direct-output mode */
- iflevel= /* #if... nesting level = 0 */
- skiplevel= /* #if... not encountered */
- macptr= /* clear the macro pool */
- csp = /* stack ptr (relative) */
- errflag= /* not skipping errors till ";" */
- eof= /* not eof yet */
- ncmp= /* not in compound statement */
- files=
- filearg=
- quote[1]=0;
- func1= /* first function */
- ccode=1; /* enable preprocessing */
- wqptr=wq; /* clear while queue */
- quote[0]='"'; /* fake a quote literal */
- input=input2=EOF;
- ask(); /* get user options */
- openfile(); /* and initial input file */
- preprocess(); /* fetch first line */
- #ifdef DYNAMIC
- symtab=calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1);
- #endif
- locptr=STARTLOC;
- glbptr=STARTGLB;
- glbflag=1;
- ctext=0;
- header(); /* intro code */
- setops(); /* set values in op arrays */
- parse(); /* process ALL input */
- outside(); /* verify outside any function */
- trailer(); /* follow-up code */
- fclose(output);
- }
-
- /*
- ** process all input text
- **
- ** At this level, only static declarations,
- ** defines, includes and function
- ** definitions are legal...
- */
- parse() {
- while (eof==0) {
- if(amatch("extern", 6)) dodeclare(EXTERNAL);
- else if(amatch("static", 6)) dodeclare(STATIC);
- else if(dodeclare(GLOBAL)) ;
- else if(match("#asm")) doasm();
- else if(match("#include")) doinclude();
- else if(match("#define")) addmac();
- else newfunc();
- blanks(); /* force eof if pending */
- }
- }
-
- /*
- ** dump the literal pool
- */
- dumplits(size) int size; {
- int j, k; k=0;
- while (k < litptr) {
- poll(1); /* allow program interruption */
- if (size == 1) gen_code(_DB, NULL);
- else gen_code(_DW, NULL);
- j = 10;
- while(j--) {
- outdec(getint(litq+k, size));
- k += size;
- if(j == 0 || k >= litptr) {nl(); break;}
- outbyte(',');
- }
- }
- }
-
- /*
- ** dump zeroes for default initial values
- */
- dumpzero(size, count) int size, count; {
- if(count > 0) {
- if (size == 1) gen_code(_DBZERO, count);
- else gen_code(_DWZERO, count);
- }
- }
-
- /*
- ** verify compile ends outside any function
- */
- outside() {
- if (ncmp) error("no closing bracket");
- }
-
- /*
- ** get run options
- */
- ask() {
- int i;
- i=listfp=nxtlab=0;
- output=stdout;
- #ifdef OPTIMIZE
- optimize=YES;
- #endif
- alarm=monitor=pause=NO;
- line=mline;
- while(getarg(++i, line, LINESIZE, argcs, argvs)!=EOF) {
- if(line[0]!='-') continue;
- if((toupper(line[1])=='L')&(isdigit(line[2]))&(line[3]<=' ')) {
- listfp=line[2]-'0';
- continue;
- }
- #ifdef OPTIMIZE
- if(toupper(line[1])=='N' && toupper(line[2])=='O' && line[3]<=' ') {
- optimize=NO;
- continue;
- }
- #endif
- if(line[2]<=' ') {
- if(toupper(line[1])=='A') {alarm=YES; continue;}
- if(toupper(line[1])=='M') {monitor=YES; continue;}
- if(toupper(line[1])=='P') {pause=YES; continue;}
- }
- #ifndef LINK
- if(toupper(line[1])=='B') {
- bump(0); bump(2);
- if(number(&nxtlab)) continue;
- }
- #endif
- sout("usage: cc [file]... [-m] [-a] [-p] [-l#]", stderr);
- #ifdef OPTIMIZE
- sout(" [-no]", stderr);
- #endif
- #ifndef LINK
- sout(" [-b#]", stderr);
- #endif
- sout("\n", stderr);
- abort(ERRCODE);
- }
- }
-
- /*
- ** input and output file opens
- */
- openfile() { /* entire function revised */
- char outfn[15];
- int i, j, ext;
- input=EOF;
- while(getarg(++filearg, pline, LINESIZE, argcs, argvs)!=EOF) {
- if(pline[0]=='-') continue;
- ext = NO;
- i = -1;
- j = 0;
- while(pline[++i]) {
- if(pline[i] == '.') {
- ext = YES;
- break;
- }
- if(j < 10) outfn[j++] = pline[i];
- }
- if(!ext) {
- strcpy(pline + i, ".C");
- }
- input = mustopen(pline, "r");
- if(!files && isatty(stdout)) {
- strcpy(outfn + j, ".ASM");
- output = mustopen(outfn, "w");
- }
- files=YES;
- kill();
- return;
- }
- if(files++) eof=YES;
- else input=stdin;
- kill();
- }
-
- /*
- ** open a file with error checking
- */
- mustopen(fn, mode) char *fn, *mode; {
- int fd;
- if(fd = fopen(fn, mode)) return fd;
- sout("open error on ", stderr);
- lout(fn, stderr);
- abort(ERRCODE);
- }
-
- setops() {
- op2[ 0]= op[ 0]= _OR; /* heir5 */
- op2[ 1]= op[ 1]= _XOR; /* heir6 */
- op2[ 2]= op[ 2]= _AND; /* heir7 */
- op2[ 3]= op[ 3]= _EQ; /* heir8 */
- op2[ 4]= op[ 4]= _NE;
- op2[ 5]=_ULE; op[ 5]= _LE; /* heir9 */
- op2[ 6]=_UGE; op[ 6]= _GE;
- op2[ 7]=_ULT; op[ 7]= _LT;
- op2[ 8]=_UGT; op[ 8]= _GT;
- op2[ 9]= op[ 9]= _ASR; /* heir10 */
- op2[10]= op[10]= _ASL;
- op2[11]= op[11]= _ADD; /* heir11 */
- op2[12]= op[12]= _SUB;
- op2[13]= op[13]=_MULT; /* heir12 */
- op2[14]= op[14]= _DIV;
- op2[15]= op[15]= _MOD;
- }
-
- >>> CC12.C 7088
- /*
- ** open an include file
- */
- doinclude() {
- int i; char str[30];
- blanks(); /* skip over to name */
- if(*lptr == '"' || *lptr == '<') ++lptr;
- i=0;
- while(lptr[i] && lptr[i] != '"' && lptr[i] != '>' && lptr[i] != '\n') {
- str[i] = lptr[i];
- ++i;
- }
- str[i] = NULL;
- if((input2=fopen(str,"r")) == NULL) {
- input2 = EOF;
- error("open failure on include file");
- }
- kill(); /* make next read come from new file (if open) */
- }
-
- /*
- ** test for global declarations
- */
- dodeclare(class) int class; {
- if(amatch("char",4)) {
- declglb(CCHAR, class);
- ns();
- return 1;
- }
- else if((amatch("int",3))|(class==EXTERNAL)|(class==STATIC)) {
- declglb(CINT, class);
- ns();
- return 1;
- }
- return 0;
- }
-
- /*
- ** declare a static variable
- */
- declglb(type, class) int type, class; {
- int k, j;
- while(1) {
- if(endst()) return; /* do line */
- if(match("(*")|match("*")) {
- j=POINTER;
- k=0;
- }
- else {
- j=VARIABLE;
- k=1;
- }
- if (symname(ssname, YES)==0) illname();
- if(findglb(ssname)) multidef(ssname);
- if(match(")")) ;
- if(match("()")) j=FUNCTION;
- else if (match("[")) {
- paerror(j);
- k=needsub(); /* get size */
- j=ARRAY; /* !0=array */
- }
- if(class==EXTERNAL) external(ssname, type>>2, j);
- else if(j!=FUNCTION) j=initials(type>>2, j, k);
- addsym(ssname, j, type, k, &glbptr, class);
- if (match(",")==0) return; /* more? */
- }
- }
-
- /*
- ** declare local variables
- */
- declloc(typ) int typ; {
- int k,j;
- if(swactive) error("not allowed in switch");
- #ifdef STGOTO
- if(noloc) error("not allowed with goto");
- #endif
- if(declared < 0) error("must declare first in block");
- while(1) {
- while(1) {
- if(endst()) return;
- if(match("(*") | match("*")) j=POINTER;
- else j=VARIABLE;
- if (symname(ssname, YES)==0) illname();
- if(match(")")) ;
- if(match("()")) j=FUNCTION;
- /* no multidef check, block-locals are together */
- k=BPW;
- if (match("[")) {
- paerror(j);
- if(k=needsub()) {
- j=ARRAY;
- if(typ==CINT)k=k<<LBPW;
- }
- else {j=POINTER; k=BPW;}
- }
- else if((typ==CCHAR)&(j==VARIABLE)) k=SBPC;
- declared = declared + k;
- addsym(ssname, j, typ, csp - declared, &locptr, AUTOMATIC);
- break;
- }
- if (match(",")==0) return;
- }
- }
-
- /*
- ** test for pointer array (unsupported)
- */
- paerror(j) int j; {
- if(j==POINTER) error("no pointer arrays");
- }
-
- /*
- ** initialize global objects
- */
- initials(size, ident, dim) int size, ident, dim; {
- int savedim;
- litptr=0;
- if(dim==0) dim = -1;
- savedim=dim;
- public(size, ident);
- if(match("=")) {
- if(match("{")) {
- while(dim) {
- init(size, ident, &dim);
- if(match(",")==0) break;
- }
- needtoken("}");
- }
- else init(size, ident, &dim);
- }
- if((dim == -1)&(dim==savedim)) {
- stowlit(0, size=BPW);
- ident=POINTER;
- }
- dumplits(size);
- dumpzero(size, dim);
- return ident;
- }
-
- /*
- ** evaluate one initializer
- */
- init(size, ident, dim) int size, ident, *dim; {
- int value;
- if(qstr(&value)) {
- if((ident==VARIABLE)|(size!=1))
- error("must assign to char pointer or array");
- *dim = *dim - (litptr - value);
- if(ident==POINTER) point();
- }
- else if(constexpr(&value)) {
- if(ident==POINTER) error("cannot assign to pointer");
- stowlit(value, size);
- *dim = *dim - 1;
- }
- }
-
- /*
- ** get required array size
- */
- needsub() {
- int val;
- if(match("]")) return 0; /* null size */
- if (constexpr(&val)==0) val=1;
- if (val<0) {
- error("negative size illegal");
- val = -val;
- }
- needtoken("]"); /* force single dimension */
- return val; /* and return size */
- }
-
- /*
- ** begin a function
- **
- ** called from "parse" and tries to make a function
- ** out of the following text
- */
- newfunc() {
- char *ptr;
- #ifdef STGOTO
- nogo = /* enable goto statements */
- noloc = 0; /* enable block-local declarations */
- #endif
- lastst= /* no statement yet */
- litptr=0; /* clear lit pool */
- litlab=getlabel(); /* label next lit pool */
- locptr=STARTLOC; /* clear local variables */
- if(monitor) lout(line, stderr);
- if (symname(ssname, YES)==0) {
- error("illegal function or declaration");
- kill(); /* invalidate line */
- return;
- }
- if(ptr=findglb(ssname)) { /* already in symbol table ? */
- if(ptr[IDENT]!=FUNCTION) multidef(ssname);
- else if(ptr[OFFSET]==FUNCTION) multidef(ssname);
- else {
- /* earlier assumed to be a function */
- ptr[OFFSET]=FUNCTION;
- ptr[CLASS]=GLOBAL;
- }
- }
- else
- addsym(ssname, FUNCTION, CINT, FUNCTION, &glbptr, GLOBAL);
- if(match("(")==0) error("no open paren");
- public(CINT>>2, FUNCTION);
- locptr=STARTLOC;
- argstk=0; /* init arg count */
- while(match(")")==0) { /* then count args */
- /* any legal name bumps arg count */
- if(symname(ssname, YES)) {
- if(findloc(ssname)) multidef(ssname);
- else {
- addsym(ssname, 0, 0, argstk, &locptr, AUTOMATIC);
- argstk=argstk+BPW;
- }
- }
- else {error("illegal argument name");junk();}
- blanks();
- /* if not closing paren, should be comma */
- if(streq(lptr,")")==0) {
- if(match(",")==0) error("no comma");
- }
- if(endst()) break;
- }
- csp=0; /* preset stack ptr */
- argtop=argstk+BPW; /* account for the pushed BP */
- while(argstk) {
- /* now let user declare what types of things */
- /* those arguments were */
- if(amatch("char",4)) {doargs(CCHAR);ns();}
- else if(amatch("int",3)) {doargs(CINT);ns();}
- else {error("wrong number of arguments");break;}
- }
- gen_code(_FUNC, 0);
- statement();
- #ifdef STGOTO
- if(lastst != STRETURN && lastst != STGOTO) gen_code(_RET, 0);
- #else
- if(lastst != STRETURN) gen_code(_RET, 0);
- #endif
- if(litptr) {
- toseg(DATASEG);
- gen_code(_RLAB, litlab);
- dumplits(1); /* dump literals */
- }
- }
-
- /*
- ** declare argument types
- **
- ** called from "newfunc" this routine adds an entry in the
- ** local symbol table for each named argument. The arguments are
- ** of type 't'.
- */
- doargs(t) int t; {
- int j, legalname;
- char c, *argptr;
- while(1) {
- if(argstk==0) return; /* no arguments */
- if(match("(*")|match("*")) j=POINTER; else j=VARIABLE;
- if((legalname=symname(ssname, YES))==0) illname();
- if(match(")")) ;
- if(match("()")) ;
- if(match("[")) { /* is it a pointer? */
- paerror(j);
- while(inbyte()!=']') if(endst()) break; /*skip "[...]" */
- j=POINTER; /* add entry as pointer */
- }
- if(legalname) {
- if(argptr=findloc(ssname)) {
- /* add details of type and address */
- argptr[IDENT]=j;
- argptr[TYPE]=t;
- putint(argtop-getint(argptr+OFFSET, OFFSIZE), argptr+OFFSET, OFFSIZE);
- }
- else error("not an argument");
- }
- argstk=argstk-BPW; /* cnt down */
- if(endst())return;
- if(match(",")==0) error("no comma");
- }
- }
-
- >>> CC13.C 7407
- /*
- ** statement parser
- **
- ** called whenever syntax requires a statement
- ** this routine performs that statement
- ** and returns a number telling which one
- */
- statement() {
- if ((ch==0) & (eof)) return;
- else if(amatch("static",6)){declglb(STATIC);ns();}
- else if(amatch("char",4)) {declloc(CCHAR);ns();}
- else if(amatch("int",3)) {declloc(CINT);ns();}
- else {
- if(declared >= 0) {
- #ifdef STGOTO
- if(ncmp > 1) nogo=declared; /* disable goto if any */
- #endif
- gen_code(_MODSTK, csp - declared);
- declared = -1;
- }
- if(match("{")) compound();
- else if(amatch("if",2)) {doif(); lastst=STIF;}
- else if(amatch("while",5)) {dowhile(); lastst=STWHILE;}
- #ifdef STDO
- else if(amatch("do",2)) {dodo(); lastst=STDO;}
- #endif
- #ifdef STFOR
- else if(amatch("for",3)) {dofor(); lastst=STFOR;}
- #endif
- #ifdef STSWITCH
- else if(amatch("switch",6)) {doswitch(); lastst=STSWITCH;}
- else if(amatch("case",4)) {docase(); lastst=STCASE;}
- else if(amatch("default",7)) {dodefault(); lastst=STDEF;}
- #endif
- #ifdef STGOTO
- else if(amatch("goto", 4)) {dogoto(); lastst=STGOTO;}
- else if(dolabel()) lastst=STLABEL;
- #endif
- else if(amatch("return",6)) {doreturn();ns(); lastst=STRETURN;}
- else if(amatch("break",5)) {dobreak();ns(); lastst=STBREAK;}
- else if(amatch("continue",8)){docont();ns(); lastst=STCONT;}
- else if(match(";")) errflag=0;
- else if(match("#asm")) {doasm(); lastst=STASM;}
- else {doexpr();ns(); lastst=STEXPR;}
- }
- return lastst;
- }
-
- /*
- ** semicolon enforcer
- **
- ** called whenever syntax requires a semicolon
- */
- ns() {
- if(match(";")==0) error("no semicolon");
- else errflag=0;
- }
-
- compound() {
- int savcsp;
- char *savloc;
- savcsp=csp;
- savloc=locptr;
- declared=0; /* may now declare local variables */
- ++ncmp; /* new level open */
- while (match("}")==0)
- if(eof) {
- error("no final }");
- break;
- }
- else statement(); /* do one */
- --ncmp; /* close current level */
- #ifdef STGOTO
- if(lastst != STRETURN && lastst != STGOTO)
- #else
- if(lastst != STRETURN)
- #endif
- gen_code(_MODSTK, savcsp); /* delete local variable space */
- csp = savcsp;
- #ifdef STGOTO
- cptr=savloc; /* retain labels */
- while(cptr < locptr) {
- cptr2=nextsym(cptr);
- if(cptr[IDENT] == LABEL) {
- while(cptr < cptr2) *savloc++ = *cptr++;
- }
- else cptr=cptr2;
- }
- #endif
- locptr=savloc; /* delete local symbols */
- declared = -1; /* may not declare variables */
- }
-
- doif() {
- int flab1,flab2;
- flab1=getlabel(); /* get label for false branch */
- test(flab1, YES); /* get expression, and branch false */
- statement(); /* if true, do a statement */
- if (amatch("else",4)==0) { /* if...else ? */
- /* simple "if"...print false label */
- gen_code(_LABEL, flab1);
- return; /* and exit */
- }
- flab2=getlabel();
- #ifdef STGOTO
- if((lastst != STRETURN)&(lastst != STGOTO)) gen_code(_JUMP, flab2);
- #else
- if(lastst != STRETURN) gen_code(_JUMP, flab2);
- #endif
- gen_code(_LABEL, flab1); /* print false label */
- statement(); /* and do "else" clause */
- gen_code(_LABEL, flab2); /* print true label */
- }
-
- doexpr() {
- int const, val;
- int *before, *start;
- while(1) {
- setstage(&before, &start);
- expression(&const, &val);
- clearstage(before, start);
- if(ch != ',') break;
- bump(1);
- }
- }
-
- dowhile() {
- int wq[4]; /* allocate local queue */
- addwhile(wq); /* add entry to queue for "break" */
- gen_code(_LABEL, wq[WQLOOP]); /* loop label */
- test(wq[WQEXIT], YES); /* see if true */
- statement(); /* if so, do a statement */
- gen_code(_JUMP, wq[WQLOOP]); /* loop to label */
- gen_code(_LABEL, wq[WQEXIT]); /* exit label */
- delwhile(); /* delete queue entry */
- }
-
- #ifdef STDO
- dodo() {
- int wq[4], top;
- addwhile(wq);
- gen_code(_LABEL, top=getlabel());
- statement();
- needtoken("while");
- gen_code(_LABEL, wq[WQLOOP]);
- test(wq[WQEXIT], YES);
- gen_code(_JUMP, top);
- gen_code(_LABEL, wq[WQEXIT]);
- delwhile();
- ns();
- }
- #endif
-
- #ifdef STFOR
- dofor() {
- int wq[4], lab1, lab2;
- addwhile(wq);
- lab1=getlabel();
- lab2=getlabel();
- needtoken("(");
- if(match(";")==0) {
- doexpr(); /* expr 1 */
- ns();
- }
- gen_code(_LABEL, lab1);
- if(match(";")==0) {
- test(wq[WQEXIT], NO); /* expr 2 */
- ns();
- }
- gen_code(_JUMP, lab2);
- gen_code(_LABEL, wq[WQLOOP]);
- if(match(")")==0) {
- doexpr(); /* expr 3 */
- needtoken(")");
- }
- gen_code(_JUMP, lab1);
- gen_code(_LABEL, lab2);
- statement();
- gen_code(_JUMP, wq[WQLOOP]);
- gen_code(_LABEL, wq[WQEXIT]);
- delwhile();
- }
- #endif
-
- #ifdef STSWITCH
- doswitch() {
- int wq[4], endlab, swact, swdef, *swnex, *swptr;
- swact=swactive;
- swdef=swdefault;
- swnex=swptr=swnext;
- addwhile(wq);
- *(wqptr + WQLOOP - WQSIZ) = 0;
- needtoken("(");
- doexpr(); /* evaluate switch expression */
- needtoken(")");
- swdefault=0;
- swactive=1;
- gen_code(_JUMP, endlab=getlabel());
- statement(); /* cases, etc. */
- gen_code(_JUMP, wq[WQEXIT]);
- gen_code(_LABEL, endlab);
- gen_code(_SW, 0); /* match cases */
- while(swptr < swnext) {
- gen_code(_DEFLABEL, *swptr++);
- gen_code(_DEFWORD, *swptr++); /* case value */
- }
- gen_code(_DEFWORD, 0);
- if(swdefault) gen_code(_JUMP, swdefault);
- gen_code(_LABEL, wq[WQEXIT]);
- delwhile();
- swnext=swnex;
- swdefault=swdef;
- swactive=swact;
- }
-
- docase() {
- if(swactive==0) error("not in switch");
- if(swnext > swend) {
- error("too many cases");
- return;
- }
- gen_code(_LABEL, *swnext++ = getlabel());
- constexpr(swnext++);
- needtoken(":");
- }
-
- dodefault() {
- if(swactive) {
- if(swdefault) error("multiple defaults");
- }
- else error("not in switch");
- needtoken(":");
- gen_code(_LABEL, swdefault=getlabel());
- }
- #endif
-
- #ifdef STGOTO
- dogoto() {
- if(nogo > 0) error("not allowed with block-locals");
- else noloc = 1;
- if(symname(ssname, YES)) gen_code(_JUMP, addlabel());
- else error("bad label");
- ns();
- }
-
- dolabel() {
- char *savelptr;
- blanks();
- savelptr=lptr;
- if(symname(ssname, YES)) {
- if(gch()==':') {
- gen_code(_LABEL, addlabel());
- return 1;
- }
- else bump(savelptr-lptr);
- }
- return 0;
- }
-
- addlabel() {
- if(cptr=findloc(ssname)) {
- if(cptr[IDENT]!=LABEL) error("not a label");
- }
- else cptr=addsym(ssname, LABEL, LABEL, getlabel(), &locptr, LABEL);
- return (getint(cptr+OFFSET, OFFSIZE));
- }
- #endif
-
- doreturn() {
- int savcsp;
- if(endst()==0) doexpr();
- savcsp = csp;
- gen_code(_MODSTK, 0);
- gen_code(_RET, 0);
- csp = savcsp;
- }
-
- dobreak() {
- int *ptr;
- if ((ptr=readwhile(wqptr))==0) return;
- gen_code(_MODSTK, ptr[WQSP]);
- gen_code(_JUMP, ptr[WQEXIT]);
- }
-
- docont() {
- int *ptr;
- ptr = wqptr;
- while (1) {
- if ((ptr=readwhile(ptr))==0) return;
- if (ptr[WQLOOP]) break;
- }
- gen_code(_MODSTK, ptr[WQSP]);
- gen_code(_JUMP, ptr[WQLOOP]);
- }
-
- doasm() {
- ccode=0; /* mark mode as "asm" */
- while (1) {
- inline();
- if (match("#endasm")) break;
- if(eof)break;
- sout(line, output);
- }
- kill();
- ccode=1;
- }
-
- >>> CC2.C 650
- /*
- ** Small-C Compiler Part 2
- */
- #include <stdio.h>
- #include "cc.def"
-
- extern char
- #ifdef DYNAMIC
- *symtab,
- *macn,
- *macq,
- *pline,
- *mline,
- #else
- symtab[SYMTBSZ],
- macn[MACNSIZE],
- macq[MACQSIZE],
- pline[LINESIZE],
- mline[LINESIZE],
- #endif
- #ifdef OPTIMIZE
- optimize,
- #endif
- alarm, *glbptr, *line, *lptr, *cptr, *cptr2, *cptr3,
- *locptr, msname[NAMESIZE], pause, quote[2];
-
- extern int
- #ifdef DYNAMIC
- *wq,
- #else
- wq[WQTABSZ],
- #endif
- ccode, ch, csp, eof, errflag, iflevel,
- input, input2, listfp, macptr, nch,
- nxtlab, op[16], opindex, opsize, output, pptr,
- skiplevel, *wqptr;
-
- #include "cc21.c"
- #include "cc22.c"
-
- >>> CC21.C 4262
- junk() {
- if(an(inbyte())) while(an(ch)) gch();
- else while(an(ch)==0) {
- if(ch==0) break;
- gch();
- }
- blanks();
- }
-
- endst() {
- blanks();
- return ((streq(lptr,";")|(ch==0)));
- }
-
- illname() {
- error("illegal symbol");
- junk();
- }
-
-
- multidef(sname) char *sname; {
- error("already defined");
- }
-
- undef(sname) char *sname; {
- error("undefined");
- }
-
- needtoken(str) char *str; {
- if (match(str)==0) error("missing token");
- }
-
- needlval() {
- error("must be lvalue");
- }
-
- findglb(sname) char *sname; {
- if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME)) return cptr;
- return 0;
- }
-
- findloc(sname) char *sname; {
- cptr = locptr - 1; /* search backward for block locals */
- while(cptr > STARTLOC) {
- cptr = cptr - *cptr;
- if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME);
- cptr = cptr - NAME - 1;
- }
- return 0;
- }
-
- addsym(sname, id, typ, value, lgptrptr, class)
- char *sname, id, typ; int value, *lgptrptr, class; {
- if(lgptrptr == &glbptr) {
- if(cptr2=findglb(sname)) return cptr2;
- if(cptr==0) {
- error("global symbol table overflow");
- return 0;
- }
- }
- else {
- if(locptr > (ENDLOC-SYMMAX)) {
- error("local symbol table overflow");
- abort(ERRCODE);
- }
- cptr = *lgptrptr;
- }
- cptr[IDENT]=id;
- cptr[TYPE]=typ;
- cptr[CLASS]=class;
- putint(value, cptr+OFFSET, OFFSIZE);
- cptr3 = cptr2 = cptr + NAME;
- while(an(*sname)) *cptr2++ = *sname++;
- if(lgptrptr == &locptr) {
- *cptr2 = cptr2 - cptr3; /* set length */
- *lgptrptr = ++cptr2;
- }
- return cptr;
- }
-
- nextsym(entry) char *entry; {
- entry = entry + NAME;
- while(*entry++ >= ' '); /* find length byte */
- return entry;
- }
-
- /*
- ** get integer of length len from address addr
- ** (byte sequence set by "putint")
- */
- getint(addr, len) char *addr; int len; {
- int i;
- i = *(addr + --len); /* high order byte sign extended */
- while(len--) i = (i << 8) | *(addr+len)&255;
- return i;
- }
-
- /*
- ** put integer i of length len into address addr
- ** (low byte first)
- */
- putint(i, addr, len) char *addr; int i, len; {
- while(len--) {
- *addr++ = i;
- i = i>>8;
- }
- }
-
- /*
- ** test if next input string is legal symbol name
- */
- symname(sname, ucase) char *sname; int ucase; {
- int k;char c;
- blanks();
- if(alpha(ch)==0) return (*sname=0); /*19*/
- k=0;
- while(an(ch)) {
- #ifdef UPPER
- if(ucase)
- sname[k]=toupper(gch());
- else
- #endif
- sname[k]=gch();
- if(k<NAMEMAX) ++k;
- }
- sname[k]=0;
- return 1;
- }
-
- /*
- ** return next avail internal label number
- */
- getlabel() {
- return(++nxtlab);
- }
-
- /*
- ** test if c is alphabetic
- */
- alpha(c) char c; {
- return (isalpha(c) | c=='_');
- }
-
- /*
- ** test if given character is alphanumeric
- */
- an(c) char c; {
- return (alpha(c) | isdigit(c));
- }
-
- addwhile(ptr) int ptr[]; {
- int k;
- ptr[WQSP]=csp; /* and stk ptr */
- ptr[WQLOOP]=getlabel(); /* and looping label */
- ptr[WQEXIT]=getlabel(); /* and exit label */
- if (wqptr==WQMAX) {
- error("too many active loops");
- abort(ERRCODE);
- }
- k=0;
- while (k<WQSIZ) *wqptr++ = ptr[k++];
- }
-
- delwhile() {
- if (wqptr > wq) wqptr=wqptr-WQSIZ;
- }
-
- readwhile(ptr) int *ptr; {
- if (ptr <= wq) {
- error("out of context");
- return 0;
- }
- else return (ptr-WQSIZ);
- }
-
- white() {
- #ifdef DYNAMIC
- /* test for stack/prog overlap at deepest nesting */
- /* primary -> symname -> blanks -> white */
- avail(YES); /* abort on stack/symbol table overflow */
- #endif
- return ((*lptr<= ' ') & (*lptr!=NULL));
- }
-
- gch() {
- int c;
- if(c=ch) bump(1);
- return c;
- }
-
- bump(n) int n; {
- if(n) lptr=lptr+n;
- else lptr=line;
- if(ch = nch = *lptr) nch = *(lptr+1);
- }
-
- kill() {
- *line=0;
- bump(0);
- }
-
- inbyte() {
- while(ch==0) {
- if (eof) return 0;
- preprocess();
- }
- return gch();
- }
-
- inline() { /* numerous revisions */
- int k,unit;
- poll(1); /* allow operator interruption */
- if (input==EOF) openfile();
- if(eof) return;
- if((unit=input2)==EOF) unit=input;
- if(fgets(line, LINEMAX, unit)==NULL) {
- fclose(unit);
- if(input2!=EOF) input2=EOF;
- else input=EOF;
- *line=NULL;
- }
- else if(listfp) {
- if(listfp==output) cout(';', output);
- sout(line, listfp);
- }
- bump(0);
- }
-
- >>> CC22.C 6770
- ifline() {
- while(1) {
- inline();
- if(eof) return;
- if(match("#ifdef")) {
- ++iflevel;
- if(skiplevel) continue;
- symname(msname, NO);
- if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0)
- skiplevel=iflevel;
- continue;
- }
- if(match("#ifndef")) {
- ++iflevel;
- if(skiplevel) continue;
- symname(msname, NO);
- if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0))
- skiplevel=iflevel;
- continue;
- }
- if(match("#else")) {
- if(iflevel) {
- if(skiplevel==iflevel) skiplevel=0;
- else if(skiplevel==0) skiplevel=iflevel;
- }
- else noiferr();
- continue;
- }
- if(match("#endif")) {
- if(iflevel) {
- if(skiplevel==iflevel) skiplevel=0;
- --iflevel;
- }
- else noiferr();
- continue;
- }
- if(skiplevel) continue;
- #ifdef OLDCC
- if((listfp!=0) & (*line!=NULL)) {
- if(listfp==output) cout(';', output);
- sout(line, listfp); /*19*/
- }
- if(ch==NEWLINE) continue;
- #else
- if(ch==0) continue;
- break;
- }
- }
-
- keepch(c) char c; {
- if(pptr<LINEMAX) pline[++pptr]=c;
- }
-
- preprocess() {
- int k;
- char c;
- if(ccode) {
- line=mline;
- ifline();
- if(eof) return;
- }
- else {
- line=pline;
- inline();
- return;
- }
- pptr = -1;
- while(ch != NEWLINE && ch) {
- if(white()) {
- keepch(' ');
- while(white()) gch();
- }
- else if(ch=='"') {
- keepch(ch);
- gch();
- while((ch!='"')|((*(lptr-1)==92)&(*(lptr-2)!=92))) {
- if(ch==NULL) {
- error("no quote");
- break;
- }
- keepch(gch());
- }
- gch();
- keepch('"');
- }
- else if(ch==39) {
- keepch(39);
- gch();
- while((ch!=39)|((*(lptr-1)==92)&(*(lptr-2)!=92))) {
- if(ch==NULL) {
- error("no apostrophe");
- break;
- }
- keepch(gch());
- }
- gch();
- keepch(39);
- }
- else if((ch=='/')&(nch=='*')) {
- bump(2);
- while(((ch=='*')&(nch=='/'))==0) {
- if(ch) bump(1);
- else {
- ifline();
- if(eof) break;
- }
- }
- bump(2);
- }
- else if(an(ch)) {
- k=0;
- while((an(ch)) & (k<NAMEMAX)) {
- msname[k++]=ch;
- gch();
- }
- msname[k]=NULL;
- if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
- k=getint(cptr+NAMESIZE, 2);
- while(c=macq[k++]) keepch(c);
- while(an(ch)) gch();
- }
- else {
- k=0;
- while(c=msname[k++]) keepch(c);
- }
- }
- else keepch(gch());
- }
- if(pptr>=LINEMAX) error("line too long");
- keepch(NULL);
- line=pline;
- bump(0);
- }
-
- noiferr() {
- error("no matching #if...");
- errflag=0;
- }
-
- addmac() {
- int k;
- if(symname(msname, NO)==0) {
- illname();
- kill();
- return;
- }
- k=0;
- if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) {
- if(cptr2=cptr) while(*cptr2++ = msname[k++]);
- else {
- error("macro name table full");
- return;
- }
- }
- putint(macptr, cptr+NAMESIZE, 2);
- while(white()) gch();
- while(putmac(gch()));
- if(macptr>=MACMAX) {
- error("macro string queue full"); abort(ERRCODE);
- }
- }
-
- putmac(c) char c; {
- macq[macptr]=c;
- if(macptr<MACMAX) ++macptr;
- return c;
- }
-
- /*
- ** search for symbol match
- ** on return cptr points to slot found or empty slot
- */
- search(sname, buf, len, end, max, off)
- char *sname, *buf, *end; int len, max, off; {
- cptr=cptr2=buf+((hash(sname)%(max-1))*len);
- while(*cptr != NULL) {
- if(astreq(sname, cptr+off, NAMEMAX)) return 1;
- if((cptr=cptr+len) >= end) cptr=buf;
- if(cptr == cptr2) return (cptr=0);
- }
- return 0;
- }
-
- hash(sname) char *sname; {
- int i, c;
- i=0;
- while(c = *sname++) i=(i<<1)+c;
- return i;
- }
-
- outdec(number) int number; {
- int k,zs;
- char c, *q, *r;
- zs = 0;
- k=10000;
- if (number<0) {
- number=(-number);
- outbyte('-');
- }
- while (k>=1) {
- q=0; r=number;
- while(r >= k) {++q; r = r - k;}
- c = q + '0';
- if ((c!='0')|(k==1)|(zs)) {
- zs=1;
- outbyte(c);
- }
- number=r;
- k=k/10;
- }
- }
-
- ol(ptr) char ptr[]; {
- ot(ptr);
- nl();
- }
-
- ot(ptr) char ptr[]; {
- outstr(ptr);
- }
-
- outstr(ptr) char ptr[]; {
- poll(1); /* allow program interruption */
- /* must work with symbol table names terminated by length */
- while(*ptr >= ' ') outbyte(*ptr++);
- }
-
- /*
- ** output a name so that it can't look like a reserved word
- */
- outname(ptr) char ptr[]; {
- outstr("_");
- while(*ptr >= ' ') outbyte(toupper(*ptr++));
- }
-
- outbyte(c) char c; {
- cout(c,output);
- return c;
- }
-
- cout(c, fd) char c; int fd; {
- if(fputc(c, fd)==EOF) xout();
- }
-
- sout(string, fd) char *string; int fd; {
- if(fputs(string, fd)==EOF) xout();
- }
-
- lout(line, fd) char *line; int fd; {
- sout(line, fd);
- cout(NEWLINE, fd);
- }
-
- xout() {
- fputs("output error", stderr);
- abort(ERRCODE);
- }
-
- nl() {
- outbyte(NEWLINE);
- }
-
- col() {
- #ifdef COL
- outbyte(':');
- #endif
- }
-
- error(msg) char msg[]; {
- if(errflag) return; else errflag=1;
- lout(line, stderr);
- errout(msg, stderr);
- if(alarm) fputc(7, stderr);
- if(pause) while(fgetc(stderr) != NEWLINE);
- if(listfp>0) errout(msg, listfp);
- }
-
- errout(msg, fp) char msg[]; int fp; {
- int k; k=line+2;
- while(k++ <= lptr) cout(' ', fp);
- lout("/\\", fp);
- sout("**** ", fp); lout(msg, fp);
- }
-
- streq(str1,str2) char str1[],str2[]; {
- int k;
- k=0;
- while (str2[k]) {
- if ((str1[k])!=(str2[k])) return 0;
- ++k;
- }
- return k;
- }
-
- astreq(str1,str2,len) char str1[],str2[];int len; {
- int k;
- k=0;
- while (k<len) {
- if ((str1[k])!=(str2[k]))break;
- /*
- ** must detect end of symbol table names terminated by
- ** symbol length in binary
- */
- if(str1[k] < ' ') break;
- if(str2[k] < ' ') break;
- ++k;
- }
- if (an(str1[k]))return 0;
- if (an(str2[k]))return 0;
- return k;
- }
-
- match(lit) char *lit; {
- int k;
- blanks();
- if (k=streq(lptr,lit)) {
- bump(k);
- return 1;
- }
- return 0;
- }
-
- amatch(lit,len) char *lit;int len; {
- int k;
- blanks();
- if (k=astreq(lptr,lit,len)) {
- bump(k);
- while(an(ch)) inbyte();
- return 1;
- }
- return 0;
- }
-
- nextop(list) char *list; {
- char op[4];
- opindex=0;
- blanks();
- while(1) {
- opsize=0;
- while(*list > ' ') op[opsize++] = *list++;
- op[opsize]=0;
- if(opsize=streq(lptr, op))
- if((*(lptr+opsize) != '=')&
- (*(lptr+opsize) != *(lptr+opsize-1)))
- return 1;
- if(*list) {
- ++list;
- ++opindex;
- }
- else return 0;
- }
- }
-
- blanks() {
- while(1) {
- while(ch) {
- if(white()) gch();
- else return;
- }
- if(line==mline) return;
- preprocess();
- if(eof)break;
- }
- }
-
- >>> CC3.C 902
- /*
- ** Small-C Compiler Part 3
- */
- #include <stdio.h>
- #include "cc.def"
-
- extern char
- #ifdef DYNAMIC
- *litq,
- #else
- litq[LITABSZ],
- #endif
- *glbptr, *lptr, ssname[NAMESIZE], quote[2];
- extern int
- ch, csp, litlab, litptr, nch, op[16], op2[16],
- oper, opindex, opsize, *stagenext;
-
- /* entries in lval[] */
- #define SYMTBL 0 /* symbol table address, else 0 for constant */
- #define TYPEIND 1 /* type of indirect obj to fetch, else 0 for static */
- #define TYPEPA 2 /* type of pointer or array, else 0 for all other */
- #define CONEXP 3 /* true if constant expression */
- #define CONVAL 4 /* value of constant expression */
- #define REG2 5 /* true if secondary register altered*/
- #define OPER 6 /* code of highest/last binary operator */
- #define STAGE 7 /* stage address of "oper 0" code, else 0 */
-
- #include "cc31.c"
- #include "cc32.c"
- #include "cc33.c"
-
- >>> CC31.C 8321
- /*
- ** lval[0] - symbol table address, else 0 for constant
- ** lval[1] - type of indirect obj to fetch, else 0 for static
- ** lval[2] - type of pointer or array, else 0 for all other
- ** lval[3] - true if constant expression
- ** lval[4] - value of constant expression (+ auxiliary uses)
- ** lval[5] - true if secondary register altered
- ** lval[6] - code of highest/last binary operator
- ** lval[7] - stage address of "oper 0" code, else 0
- */
-
- /*
- ** skim over terms adjoining || and && operators
- */
- skim(opstr, testfunc, dropval, endval, hier, lval)
- char *opstr;
- int testfunc, dropval, endval, (*hier)(), lval[]; {
- int k, hits, droplab, endlab;
- hits=0;
- while(1) {
- k=plnge1(hier, lval);
- if(nextop(opstr)) {
- bump(opsize);
- if(hits==0) {
- hits=1;
- droplab=getlabel();
- }
- dropout(k, testfunc, droplab, lval);
- }
- else if(hits) {
- dropout(k, testfunc, droplab, lval);
- gen_code(_IMMED, endval);
- gen_code(_JUMP, endlab=getlabel());
- gen_code(_LABEL, droplab);
- gen_code(_IMMED, dropval);
- gen_code(_LABEL, endlab);
- lval[TYPEIND] = lval[TYPEPA] = lval[CONEXP] =
- lval[CONVAL] = lval[STAGE] = 0;
- return 0;
- }
- else return k;
- }
- }
-
- /*
- ** test for early dropout from || or && evaluations
- */
- dropout(k, testfunc, exit1, lval)
- int k, testfunc, exit1, lval[]; {
- if(k) rvalue(lval);
- else if(lval[CONEXP]) gen_code(_IMMED, lval[CONVAL]);
- gen_code(testfunc, exit1); /* jumps on false */
- }
-
- /*
- ** plunge to a lower level
- */
- plnge(opstr, opoff, hier, lval)
- char *opstr;
- int opoff, (*hier)(), lval[]; {
- int k, lval2[8];
- k=plnge1(hier, lval);
- if(nextop(opstr)==0) return k;
- if(k) rvalue(lval);
- while(1) {
- if(nextop(opstr)) {
- bump(opsize);
- opindex=opindex+opoff;
- plnge2(op[opindex], op2[opindex], hier, lval, lval2);
- }
- else return 0;
- }
- }
-
- /*
- ** unary plunge to lower level
- */
- plnge1(hier, lval) int (*hier)(), lval[]; {
- int *before, *start;
- int k;
- setstage(&before, &start);
- k=(*hier)(lval);
- if(lval[CONEXP]) clearstage(before,0); /* load constant later */
- return k;
- }
-
- /*
- ** binary plunge to lower level
- */
- plnge2(oper, oper2, hier, lval, lval2)
- int oper, oper2, (*hier)(), lval[], lval2[]; {
- int *before, *start;
- setstage(&before, &start);
- lval[REG2]=1; /* flag secondary register used */
- lval[STAGE]=0; /* flag as not "... oper 0" syntax */
- if(lval[CONEXP]) { /* constant on left side not yet loaded */
- if(plnge1(hier, lval2)) rvalue(lval2);
- if(lval[CONVAL]==0) lval[STAGE]=stagenext;
- gen_code(_IMMED2, lval[CONVAL]<<dbltest(oper, lval2, lval));
- }
- else { /* non-constant on left side */
- gen_code(_PUSH, 0);
- if(plnge1(hier, lval2)) rvalue(lval2);
- if(lval2[CONEXP]) { /* constant on right side */
- if(lval2[CONVAL]==0) lval[STAGE]=start;
- csp+=2;
- clearstage(before, 0);
- if(oper==_ADD) { /* may test other commutative operators */
- gen_code(_IMMED2, lval2[CONVAL]<<dbltest(oper, lval, lval2));
- }
- else {
- gen_code(_MOVE, 0);
- gen_code(_IMMED, lval2[CONVAL]<<dbltest(oper, lval, lval2));
- }
- }
- else { /* non-constants on both sides */
- gen_code(_POP, 0);
- if((oper==_ADD)|(oper==_SUB)) {
- if(dbltest(oper, lval, lval2)) gen_code(_DBL, 0);
- if(dbltest(oper, lval2, lval)) gen_code(_DBL2, 0);
- }
- }
- }
- if(oper) {
- if(lval[CONEXP]=lval[CONEXP]&lval2[CONEXP]) {
- lval[CONVAL]=calc(lval[CONVAL], oper, lval2[CONVAL]);
- clearstage(before, 0);
- lval[REG2]=0;
- }
- else {
- if((lval[TYPEPA]==0)&(lval2[TYPEPA]==0)) { /* neither is a pointer */
- gen_code(oper, 0);
- lval[OPER]=oper; /* identify the operator */
- }
- else {
- gen_code(oper2, 0);
- lval[OPER]=oper2; /* identify the operator */
- }
- }
- if(oper==_SUB) {
- /* if subtracting two pointers to integers */
- if((lval[TYPEPA]==CINT)&(lval2[TYPEPA]==CINT)) {
- gen_code(_SWAP, 0);
- gen_code(_IMMED, 1);
- gen_code(_ASR, 0); /** div by 2 **/
- }
- }
- if((oper==_SUB)|(oper==_ADD)) result(lval, lval2);
- }
- }
-
- calc(left, oper, right) int left, oper, right; {
- switch(oper) {
- case _OR: return (left | right);
- case _XOR: return (left ^ right);
- case _AND: return (left & right);
- case _EQ: return (left == right);
- case _NE: return (left != right);
- case _LE: return (left <= right);
- case _GE: return (left >= right);
- case _LT: return (left < right);
- case _GT: return (left > right);
- case _ASR: return (left >> right);
- case _ASL: return (left << right);
- case _ADD: return (left + right);
- case _SUB: return (left - right);
- case _MULT: return (left * right);
- case _DIV: return (left / right);
- case _MOD: return (left % right);
- default: return 0;
- }
- }
-
- expression(const, val) int *const, *val; {
- int lval[8];
- if(hier1(lval)) rvalue(lval);
- if(lval[CONEXP]) {
- *const=1;
- *val=lval[CONVAL];
- }
- else *const=0;
- }
-
- hier1(lval) int lval[]; {
- int k, lval2[8], lval3[2], oper;
- k=plnge1(hier2, lval);
- if(lval[CONEXP]) gen_code(_IMMED, lval[CONVAL]);
- if(match("|=")) oper=_OR;
- else if(match("^=")) oper=_XOR;
- else if(match("&=")) oper=_AND;
- else if(match("+=")) oper=_ADD;
- else if(match("-=")) oper=_SUB;
- else if(match("*=")) oper=_MULT;
- else if(match("/=")) oper=_DIV;
- else if(match("%=")) oper=_MOD;
- else if(match(">>=")) oper=_ASR;
- else if(match("<<=")) oper=_ASL;
- else if(match("=")) oper=0;
- else return k;
- if(k==0) {needlval(); return 0;}
- lval3[SYMTBL] = lval[SYMTBL];
- lval3[TYPEIND] = lval[TYPEIND];
- if(lval[TYPEIND]) { /* if we have a pointer to the variable, save it.*/
- if(oper) {
- gen_code(_PUSH, 0);
- rvalue(lval);
- }
- plnge2(oper, oper, hier1, lval, lval2);
- if(oper) gen_code(_POP, 0);
- }
- else {
- if(oper) {
- rvalue(lval);
- plnge2(oper, oper, hier1, lval, lval2);
- }
- else {
- if(hier1(lval2)) rvalue(lval2);
- lval[REG2]=lval2[REG2];
- }
- }
- store(lval3);
- return 0;
- }
-
- hier2(lval) int lval[]; {
- int k, falselab, endlab;
- int *before, *after;
- int const, retconst, retval;
- retconst = NO; /* assume non-constant */
- k = plnge1(hier3, lval);
- if (lval[CONEXP] && lval[CONVAL]) const = 1;
- else if (lval[CONEXP] && !lval[CONVAL]) const = -1;
- else const = 0;
- if (match("?")==0) return k;
- if (!const) dropout(k, _NE0, falselab = getlabel(), lval);
- setstage(&before, &after); /* prepare to delete code */
- if (plnge1(hier3, lval)) rvalue(lval);
- else if (lval[CONEXP]) gen_code(_IMMED, lval[CONVAL]);
- if (const<0) clearstage(before, 0); /* if false, delete 'then' expr */
- else if (const>0) {
- retconst = lval[CONEXP];
- retval = lval[CONVAL];
- }
- needtoken(":");
- if (!const) {
- gen_code(_JUMP, endlab = getlabel());
- gen_code(_LABEL, falselab);
- }
- setstage(&before, &after);
- if (plnge1(hier3, lval)) rvalue(lval);
- else if (lval[CONEXP]) gen_code(_IMMED, lval[CONVAL]);
- if (const>0) clearstage(before, 0); /* if true, delete 'else' expr */
- else if (const<0) {
- retconst = lval[CONEXP];
- retval = lval[CONVAL];
- }
- if (!const) gen_code(_LABEL, endlab);
- lval[CONEXP] = retconst;
- lval[CONVAL] = retval;
- lval[TYPEIND]=lval[TYPEPA]=lval[STAGE]=0;
- return 0;
- }
-
- hier3(lval) int lval[]; {
- return skim("||", _EQ0, 1, 0, hier4, lval);
- }
-
- hier4(lval) int lval[]; {
- return skim("&&", _NE0, 0, 1, hier5, lval);
- }
-
- hier5(lval) int lval[]; {
- return plnge("|", 0, hier6, lval);
- }
-
- hier6(lval) int lval[]; {
- return plnge("^", 1, hier7, lval);
- }
-
- hier7(lval) int lval[]; {
- return plnge("&", 2, hier8, lval);
- }
-
- hier8(lval) int lval[]; {
- return plnge("== !=", 3, hier9, lval);
- }
-
- hier9(lval) int lval[]; {
- return plnge("<= >= < >", 5, hier10, lval);
- }
-
- hier10(lval) int lval[]; {
- return plnge(">> <<", 9, hier11, lval);
- }
-
- hier11(lval) int lval[]; {
- return plnge("+ -", 11, hier12, lval);
- }
-
- hier12(lval) int lval[]; {
- return plnge("* / %", 13, hier13, lval);
- }
-
- >>> CC32.C 6090
- hier13(lval) int lval[]; {
- int k;
- char *ptr;
- if(match("++")) { /* ++lval */
- if(hier13(lval)==0) {
- needlval();
- return 0;
- }
- step(_INC, lval, 0);
- return 0;
- }
- else if(match("--")) { /* --lval */
- if(hier13(lval)==0) {
- needlval();
- return 0;
- }
- step(_DEC, lval, 0);
- return 0;
- }
- else if (match("~")) { /* ~ */
- if(hier13(lval)) rvalue(lval);
- gen_code(_COM, 0);
- lval[CONVAL] = ~ lval[CONVAL];
- return (lval[STAGE]=0);
- }
- else if (match("!")) { /* ! */
- if(hier13(lval)) rvalue(lval);
- gen_code(_LNEG, 0);
- lval[CONVAL] = ! lval[CONVAL];
- return (lval[STAGE]=0);
- }
- else if (match("-")) { /* unary - */
- if(hier13(lval)) rvalue(lval);
- gen_code(_NEG, 0);
- lval[CONVAL] = -lval[CONVAL];
- return (lval[STAGE]=0);
- }
- else if(match("*")) { /* unary * */
- if(hier13(lval)) rvalue(lval);
- if(ptr=lval[SYMTBL]) lval[TYPEIND]=ptr[TYPE];
- else lval[TYPEIND]=CINT;
- lval[TYPEPA]=0; /* flag as not pointer or array */
- lval[CONEXP]=0; /* flag as not constant */
- lval[CONVAL]=1; /* omit rvalue() on func call */
- lval[STAGE]=0;
- return 1;
- }
- else if(match("sizeof(")) { /* sizeof() */
- int *before, *start;
- setstage(&before, &start);
- k=hier13(lval);
- clearstage(before, 0);
- needtoken(")");
- lval[CONEXP]=1;
- if (lval[TYPEPA]) lval[CONVAL]=CINT>>2;
- else lval[CONVAL]=lval[TYPEIND]>>2;
- lval[TYPEPA]=lval[TYPEIND]=lval[SYMTBL]=0;
- return 0;
- }
- else if(match("&")) { /* unary & */
- if(hier13(lval)==0) {
- error("illegal address");
- return 0;
- }
- ptr=lval[SYMTBL];
- lval[TYPEPA]=ptr[TYPE];
- if(lval[TYPEIND]) return 0;
- /* global & non-array */
- gen_code(_OFFSET, ptr);
- lval[TYPEIND]=ptr[TYPE];
- return 0;
- }
- else {
- k=hier14(lval);
- if(match("++")) { /* lval++ */
- if(k==0) {
- needlval();
- return 0;
- }
- step(_INC, lval, _DEC);
- return 0;
- }
- else if(match("--")) { /* lval-- */
- if(k==0) {
- needlval();
- return 0;
- }
- step(_DEC, lval, _INC);
- return 0;
- }
- else return k;
- }
- }
-
- hier14(lval) int *lval; {
- int k, const, val, lval2[8];
- char *ptr, *before, *start;
- k=primary(lval);
- ptr=lval[SYMTBL];
- blanks();
- if((ch=='[')|(ch=='(')) {
- lval[REG2]=1; /* secondary register will be used */
- while(1) {
- if(match("[")) { /* [subscript] */
- if(ptr==0) {
- error("can't subscript");
- junk();
- needtoken("]");
- return 0;
- }
- else if(ptr[IDENT]==POINTER) rvalue(lval);
- else if(ptr[IDENT]!=ARRAY) {
- error("can't subscript");
- k=0;
- }
- setstage(&before, &start);
- lval2[CONEXP]=0;
- plnge2(0, 0, hier1, lval2, lval2); /* lval2 deadend */
- needtoken("]");
- if(lval2[CONEXP]) {
- clearstage(before, 0);
- if(lval2[CONVAL]) { /* only add if non-zero */
- if(ptr[TYPE]==CINT) gen_code(_IMMED2, lval2[CONVAL]<<LBPW);
- else gen_code(_IMMED2, lval2[CONVAL]);
- gen_code(_ADD, 0);
- }
- }
- else {
- if(ptr[TYPE]==CINT) gen_code(_DBL, 0);
- gen_code(_ADD, 0);
- }
- lval[TYPEPA]=0;
- lval[TYPEIND]=ptr[TYPE];
- k=1;
- }
- else if(match("(")) { /* function(...) */
- if(ptr==0) callfunction(0);
- else if(ptr[IDENT]!=FUNCTION) {
- if(k && !lval[CONVAL]) rvalue(lval);
- callfunction(0);
- }
- else callfunction(ptr);
- k=lval[SYMTBL]=lval[CONEXP]=lval[CONVAL]=0;
- }
- else return k;
- }
- }
- if(ptr==0) return k;
- if(ptr[IDENT]==FUNCTION) {
- gen_code(_OFFSET, ptr);
- lval[SYMTBL]=0;
- return 0;
- }
- return k;
- }
-
- primary(lval) int *lval; {
- char *ptr, sname[NAMESIZE];
- int k;
- if(match("(")) { /* (expression,...) */
- do k=hier1(lval); while(match(","));
- needtoken(")");
- return k;
- }
- putint(0, lval, 8<<LBPW); /* clear lval array */
- if(symname(sname, YES)) {
- if(ptr=findloc(sname)) {
- #ifdef STGOTO
- if(ptr[IDENT]==LABEL) {
- experr();
- return 0;
- }
- #endif
- gen_code(_GSTK, ptr);
- lval[SYMTBL]=ptr;
- lval[TYPEIND]=ptr[TYPE];
- if(ptr[IDENT]==POINTER) {
- lval[TYPEIND]=CINT;
- lval[TYPEPA]=ptr[TYPE];
- }
- if(ptr[IDENT]==ARRAY) {
- lval[TYPEPA]=ptr[TYPE];
- return 0;
- }
- else return 1;
- }
- if(ptr=findglb(sname))
- if(ptr[IDENT]!=FUNCTION) {
- lval[SYMTBL]=ptr;
- lval[TYPEIND]=0;
- if(ptr[IDENT]!=ARRAY) {
- if(ptr[IDENT]==POINTER) lval[TYPEPA]=ptr[TYPE];
- return 1;
- }
- gen_code(_OFFSET, ptr);
- lval[TYPEIND]=lval[TYPEPA]=ptr[TYPE];
- return 0;
- }
- ptr=addsym(sname, FUNCTION, CINT, 0, &glbptr, AUTOEXT);
- lval[SYMTBL]=ptr;
- lval[TYPEIND]=0;
- return 0;
- }
- if(constant(lval)==0) experr();
- return 0;
- }
-
- experr() {
- error("invalid expression");
- gen_code(_IMMED, 0);
- junk();
- }
-
- callfunction(ptr) char *ptr; { /* symbol table entry or 0 */
- int nargs, const, val;
- nargs=0;
- blanks(); /* already saw open paren */
- while(streq(lptr,")")==0) {
- if(endst()) break;
- if(ptr) {
- expression(&const, &val);
- gen_code(_PUSH,0);
- }
- else {
- gen_code(_PUSH,0);
- expression(&const, &val);
- gen_code(_SWAPSTK, 0); /* don't push addr */
- }
- nargs=nargs+BPW; /* count args*BPW */
- if (match(",")==0) break;
- }
- needtoken(")");
- if(streq(ptr+NAME, "CCARGC")==0) loadargc(nargs>>LBPW);
- if(ptr) gen_code(_CALL, ptr);
- else gen_code(_CALLSTK, 0);
- gen_code(_MODSTK, csp+nargs);
- }
-
- >>> CC33.C 4768
- /*
- ** true if val1 -> int pointer or int array and val2 not ptr or array
- */
- dbltest(oper, val1,val2) int oper, val1[], val2[]; {
- if((oper!=_ADD) && (oper!=_SUB)) return 0;
- if(val1[TYPEPA]!=CINT) return 0;
- if(val2[TYPEPA]) return 0;
- return 1;
- }
-
- /*
- ** determine type of binary operation
- */
- result(lval, lval2) int lval[], lval2[]; {
- if((lval[TYPEPA]!=0)&(lval2[TYPEPA]!=0)) {
- lval[TYPEPA]=0;
- }
- else if(lval2[TYPEPA]) {
- lval[SYMTBL]=lval2[SYMTBL];
- lval[TYPEIND]=lval2[TYPEIND];
- lval[TYPEPA] =lval2[TYPEPA];
- }
- }
-
- step(oper, lval, oper2) int oper, lval[], oper2; {
- rvalue(lval);
- gen_code(oper, lval[TYPEPA]>>2 ? lval[TYPEPA]>>2 : 1);
- store(lval);
- if(oper2) gen_code(oper2, lval[TYPEPA]>>2 ? lval[TYPEPA]>>2 : 1);
- }
-
- store(lval) int lval[]; {
- char *sym;
- if(lval[TYPEIND]) {
- /* putstk */
- if(lval[TYPEIND]==CCHAR) gen_code(_PCHAR, 0);
- else gen_code(_PINT, 0);
- }
- else {
- /* putmem */
- sym = lval[SYMTBL];
- if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) gen_code(_SCHAR, sym);
- else gen_code(_SINT, sym);
- }
- }
-
- rvalue(lval) int lval[]; {
- char *sym;
- if ((lval[SYMTBL]!=0)&(lval[TYPEIND]==0)) {
- /* getmem */
- sym = lval[SYMTBL];
- if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) gen_code(_LCHAR, sym);
- else gen_code(_LINT, sym);
- }
- else {
- /* indirect */
- if(lval[TYPEIND]==CCHAR) gen_code(_GCHAR, 0);
- else gen_code(_GINT, 0);
- }
- }
-
- test(label, parens) int label, parens; {
- int lval[8];
- int *before, *start;
- if(parens) needtoken("(");
- while(1) {
- setstage(&before, &start);
- if(hier1(lval)) rvalue(lval);
- if(match(",")) clearstage(before, start);
- else break;
- }
- if(parens) needtoken(")");
- if(lval[CONEXP]) { /* constant expression */
- clearstage(before, 0);
- if(lval[CONVAL]) return;
- gen_code(_JUMP, label);
- return;
- }
- if(lval[STAGE]) { /* stage address of "oper 0" code */
- switch(lval[OPER]) { /* operator code */
- case _EQ:
- case _ULE: zerojump(_EQ0, label, lval); break;
- case _NE:
- case _UGT: zerojump(_NE0, label, lval); break;
- case _GT: zerojump(_GT0, label, lval); break;
- case _GE: zerojump(_GE0, label, lval); break;
- case _UGE: clearstage(lval[STAGE], 0); break;
- case _LT: zerojump(_LT0, label, lval); break;
- case _ULT: zerojump(_ULT0, label, lval); break;
- case _LE: zerojump(_LE0, label, lval); break;
- default: gen_code(_TESTJUMP, label); break;
- }
- }
- else gen_code(_TESTJUMP, label);
- clearstage(before, start);
- }
-
- constexpr(val) int *val; {
- int const;
- int *before, *start;
- setstage(&before, &start);
- expression(&const, val);
- clearstage(before, 0); /* scratch generated code */
- if(const==0) error("must be constant expression");
- return const;
- }
-
- constant(lval) int lval[]; {
- lval += CONEXP;
- *lval=1; /* assume it will be a constant */
- if (number(++lval)) gen_code(_IMMED, *lval);
- else if (pstr(lval)) gen_code(_IMMED, *lval);
- else if (qstr(lval)) {
- *(lval-1)=0; /* nope, it's a string address */
- gen_code(_STRING, *lval);
- }
- else return 0;
- return 1;
- }
-
- number(val) int val[]; {
- int k, minus;
- k=minus=0;
- while(1) {
- if(match("+")) ;
- else if(match("-")) minus=1;
- else break;
- }
- if(isdigit(ch)==0) return 0;
- if (ch=='0') {
- while(ch == '0') inbyte();
- if (toupper(ch)=='X') {
- inbyte();
- while(isxdigit(ch)) {
- if (isdigit(ch)) k=k*16+(inbyte()-'0');
- else k=k*16+10+(toupper(inbyte())-'A');
- }
- }
- else while (ch>='0' && ch<='7') k=k*8+(inbyte()-'0');
- }
- else while (isdigit(ch)) k=k*10+(inbyte()-'0');
- if (minus) k=(-k);
- val[0]=k;
- return 1;
- }
-
- pstr(val) int val[]; {
- int k;
- k=0;
- if (match("'")==0) return 0;
- while(ch!='\'') k=(k&255)*256 + (litchar()&255);
- gch();
- val[0]=k;
- return 1;
- }
-
- qstr(val) int val[]; {
- char c;
- if (match(quote)==0) return 0;
- val[0]=litptr;
- while (ch!='"') {
- if(ch==0) break;
- stowlit(litchar(), 1);
- }
- gch();
- litq[litptr++]=0;
- return 1;
- }
-
- stowlit(value, size) int value, size; {
- if((litptr+size) >= LITMAX) {
- error("literal queue overflow");
- abort(ERRCODE);
- }
- putint(value, litq+litptr, size);
- litptr=litptr+size;
- }
-
- /*
- ** return current literal char & bump lptr
- */
- litchar() {
- int i, oct;
- if((ch!='\\')|(nch==0)) return gch();
- gch();
- switch(ch) {
- case 'n': gch(); return NEWLINE;
- case 't': gch(); return 9; /* HT */
- case 'b': gch(); return 8; /* BS */
- case 'f': gch(); return 12; /* FF */
- }
- i=3; oct=0;
- while(((i--)>0)&(ch>='0')&(ch<='7')) oct=(oct<<3)+gch()-'0';
- if(i==2) return gch(); else return oct;
- }
-
- >>> CC4.C 420
- /*
- ** Small-C Compiler Part 4
- */
- #include <stdio.h>
- #include "cc.def"
-
- extern char
- *cptr,
- #ifdef DYNAMIC
- *macn,
- *symtab,
- #else
- macn[MACNSIZE],
- symtab[SYMTBSZ],
- #endif
- #ifdef OPTIMIZE
- optimize,
- #endif
- ssname[NAMESIZE];
-
- extern int
- #ifdef DYNAMIC
- *stage,
- #else
- stage[STAGESIZE*2],
- #endif
- litlab, beglab, csp, output, oldseg,
- *stagenext, *stagetail, *stagelast;
-
- #include "cc41.c"
- #include "cc42.c"
-
- >>> CC41.C 4333
- /*
- ** print all assembler info before any code is generated
- ** and ensure that the segments appear in the correct order.
- */
- header() {
- toseg(CODESEG);
- ol("extrn __link: near");
- ol("extrn __eq: near");
- ol("extrn __ne: near");
- ol("extrn __le: near");
- ol("extrn __lt: near");
- ol("extrn __ge: near");
- ol("extrn __gt: near");
- ol("extrn __ule: near");
- ol("extrn __ult: near");
- ol("extrn __uge: near");
- ol("extrn __ugt: near");
- ol("extrn __lneg: near");
- ol("extrn __switch: near");
- ol("dw 0"); /* ensure non-zero code pointers, retain word alignment */
- toseg(DATASEG);
- ol("dw 0"); /* ensure non-zero data pointers, retain word alignment */
- }
-
- /*
- ** print any assembler stuff needed at the end
- */
- trailer() {
- #ifndef LINK
- if((beglab == 1)|(beglab > 9000)) {
- /* implementation dependent trailer code goes here */
- }
- #else
- cptr=STARTGLB;
- while(cptr<ENDGLB) {
- if(cptr[IDENT]==FUNCTION && cptr[CLASS]==AUTOEXT)
- external(cptr+NAME,0,FUNCTION);
- cptr+=SYMMAX;
- }
- #endif
- toseg(NULL);
- ol("END");
- }
-
- /*
- ** remember where we are in the queue in case we have to back up.
- */
- setstage(before, start) int *before, *start; {
- if((*before=stagenext)==0) stagenext=stage;
- *start=stagenext;
- }
-
- /*
- ** put code into the queue.
- */
- gen_code(func, value) int func, value; {
- int size;
- if (func==_PUSH) csp=csp-BPW;
- else if(func==_POP) csp=csp+BPW;
- else if(func==_MODSTK) {
- size=value;
- value-=csp;
- csp=size;
- }
- if(stagenext==0) {
- out_code(func,value);
- return;
- }
- if(stagenext >= stagelast) {
- error("staging buffer overflow");
- return;
- }
- stagenext[0] = func;
- stagenext[1] = value;
- stagenext = nextq(stagenext);
- }
-
- nextq(qptr) int *qptr; {
- qptr += 2;
- if(qptr >= stagelast) qptr = stage;
- return (qptr);
- }
-
- /*
- ** dump the contents of the queue.
- ** If start=0, throw away contents.
- ** If before!=0, don't dump queue yet.
- */
- clearstage(before, start) int *before, *start; {
- if(before) {stagenext = before; return;}
- if(start) dumpstage();
- stagenext = 0;
- }
-
- /*
- ** empty the queue.
- */
- dumpstage() {
- stagetail = stagenext;
- stagenext = stage;
- while(stagenext < stagetail) {
- #ifdef OPTIMIZE
- peephole();
- #endif
- out_code(stagenext[0], stagenext[1]);
- stagenext = nextq(stagenext);
- }
- }
-
- /*
- ** change to a new segment
- ** may be called with NULL, CODESEG, or DATASEG
- */
- toseg(newseg) int newseg; {
- if(oldseg==newseg) return;
- if(oldseg==CODESEG) ol("CODE ENDS");
- else if(oldseg==DATASEG) ol("DATA ENDS");
- if(newseg==CODESEG) {
- ol("CODE SEGMENT PUBLIC");
- ol("ASSUME CS:CODE, SS:DATA, DS:DATA");
- }
- else if(newseg==DATASEG)
- ol("DATA SEGMENT PUBLIC");
- oldseg = newseg;
- }
-
- /*
- ** load # args before function call
- */
- loadargc(val) int val; {
- if(search("NOCCARGC", macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) {
- gen_code(_COUNT, val);
- }
- }
-
- /*
- ** declare entry point
- */
- public(size, ident) int size, ident;{
- if (ident == FUNCTION) toseg(CODESEG);
- else toseg(DATASEG);
- #ifdef LINK
- ot("PUBLIC ");
- outname(ssname);
- nl();
- #endif
- outname(ssname);
- if (ident == FUNCTION) {col(); nl();}
- }
-
- /*
- ** declare external reference
- */
- external(name, size, ident) char *name; int size, ident; {
- #ifdef LINK
- if (ident == FUNCTION) toseg(CODESEG);
- else toseg(DATASEG);
- ot("EXTRN ");
- outname(name);
- col();
- outsize(size, ident);
- nl();
- #endif
- }
-
- /*
- ** swap primary and secondary registers
- */
- outswap() {
- ol("XCHG AX,BX");
- }
-
- /*
- ** output a label of specified number
- */
- outlabel(lab) int lab; {
- outstr("_");
- outdec(lab);
- }
-
- /*
- ** output a jump to the specified label
- */
- outjump(lab) int lab; {
- ot("JMP ");
- outlabel(lab);
- nl();
- }
-
- /*
- ** output the size of the object pointed to.
- */
- outsize(size, ident) int size, ident; {
- if ((size==1)&(ident!=POINTER)&(ident!=FUNCTION)) {outstr("BYTE");}
- else if (ident!=FUNCTION) {outstr("WORD");}
- else {outstr("NEAR");};
- }
-
- /*
- ** output a call
- */
- outcall(sname) char *sname; {
- ot("CALL ");
- outstr(sname);
- nl();
- }
-
- /*
- ** test primary register against zero and jump if false
- */
- zerojump(oper, label, lval) int oper, label, lval[]; {
- clearstage(lval[7], 0); /* purge conventional code */
- gen_code(oper, label);
- }
-
- /*
- ** point to following object(s)
- */
- point() {
- ol(" DW $+2");
- }
-
- >>> CC42.C 9580
- #ifdef OPTIMIZE
- /*
- ** Peephole Optimizer
- */
- int
- seq01[] = {_PUSH, _ANY, _POP, NULL},
- seq02[] = {_GSTK, _IMMED2, _ADD, _GINT, NULL},
- seq03[] = {_GSTK, _IMMED2, _ADD, _GCHAR, NULL},
- seq04[] = {_OFFSET, _IMMED2, _ADD, _GINT, NULL},
- seq05[] = {_OFFSET, _IMMED2, _ADD, _GCHAR, NULL},
- seq08[] = {_GSTK, _GCHAR, NULL},
- seq09[] = {_GSTK, _GINT, NULL},
- seq10[] = {_MOVE, _IMMED, _SUB, NULL},
- seq11[] = {_INC, _PINT, _DEC, NULL},
- seq12[] = {_DEC, _PINT, _INC, NULL},
- seq13[] = {_INC, _PCHAR, _DEC, NULL},
- seq14[] = {_DEC, _PCHAR, _INC, NULL},
- seq15[] = {_INC, _SINT, _DEC, NULL},
- seq16[] = {_INC, _SCHAR, _DEC, NULL},
- seq17[] = {_DEC, _SINT, _INC, NULL},
- seq18[] = {_DEC, _SCHAR, _INC, NULL},
- seq19[] = {_IMMED2, _ADD, NULL};
-
- peephole() {
- while(optimize) {
- if(peep(seq01)) { /* _PUSH_ANY_POP --> _MOVE_ANY */
- stagenext[4] = stagenext[2];
- stagenext[5] = stagenext[3];
- stagenext[2] = _MOVE;
- stagenext += 2;
- }
- else if(peep(seq02)) { /* _GSTK_IMMED2_ADD_GINT --> _GLIO */
- stagenext[6] = _GLIO;
- stagenext[7] = getint(stagenext[1]+OFFSET, OFFSIZE) + stagenext[3];
- stagenext += 6;
- }
- else if(peep(seq03)) { /* _GSTK_IMMED2_ADD_GCHAR --> _GLCO */
- stagenext[6] = _GLCO;
- stagenext[7] = getint(stagenext[1]+OFFSET, OFFSIZE) + stagenext[3];
- stagenext += 6;
- }
- else if(peep(seq04)) { /* _OFFSET_IMMED2_ADD_GINT --> _GGIO */
- stagenext[4] = _GGIO1;
- stagenext[5] = stagenext[1];
- stagenext[6] = _GGIO2;
- stagenext[7] = stagenext[3];
- stagenext += 4;
- }
- else if(peep(seq05)) { /* _OFFSET_IMMED2_ADD_GCHAR --> _GGCO */
- stagenext[4] = _GGCO1;
- stagenext[5] = stagenext[1];
- stagenext[6] = _GGCO2;
- stagenext[7] = stagenext[3];
- stagenext += 4;
- }
- else if(peep(seq08)) /* _GSTK_GCHAR --> _FCHAR */
- merge(_FCHAR);
- else if(peep(seq09)) /* _GSTK_GINT --> _FINT */
- merge(_FINT);
- else if(peep(seq10)) { /* _MOVE_IMMED_SUB --> _SUBI */
- stagenext[4] = _SUBI;
- stagenext[5] = stagenext[3];
- stagenext += 4;
- }
- else if(peep(seq11)) { /* _INC_PINT_DEC --> _INT_I */
- stagenext[4] = _INT_I;
- stagenext += 4;
- }
- else if(peep(seq12)) { /* _DEC_PINT_INC --> _INT_D */
- stagenext[4] = _INT_D;
- stagenext += 4;
- }
- else if(peep(seq13)) { /* _INC_PCHAR_DEC --> _CHAR_I */
- stagenext[4] = _CHAR_I;
- stagenext += 4;
- }
- else if(peep(seq14)) { /* _DEC_PCHAR_INC --> _CHAR_D */
- stagenext[4] = _CHAR_D;
- stagenext += 4;
- }
- else if(peep(seq15) ||
- peep(seq16)) { /* _INC_Sxxx_DEC --> _XXX_I1 */
- stagenext[2] = _XXX_I1;
- stagenext[4] = _XXX_X2;
- stagenext += 2;
- }
- else if(peep(seq17) ||
- peep(seq18)) { /* _DEC_Sxxx_INC --> _XXX_D1 */
- stagenext[2] = _XXX_D1;
- stagenext[4] = _XXX_X2;
- stagenext += 2;
- }
- else if(peep(seq19)) /* _IMMED2_ADD --> _ADDI */
- merge(_ADDI);
- else break;
- }
- }
-
- /*
- ** peep into the staging buffer for a match
- */
- peep(seq) int *seq; {
- int *next;
- next = stagenext;
- while(*seq) {
- if(next >= stagetail || (*seq != _ANY && *seq != *next))
- return (NO);
- next += 2;
- ++seq;
- }
- return (YES);
- }
-
- /*
- ** Merge top two p-codes into one with code "func" and the top value.
- */
- merge(func) int func; {
- stagenext[2] = func;
- stagenext[3] = stagenext[1];
- stagenext += 2;
- }
- #endif
-
- /*
- ** take code out of the queue.
- */
- out_code(func, value) int func, value; {
- char *str;
- str = value;
- switch(func) {
- case _LABEL: {outlabel(value); col(); nl(); break;}
- case _RLAB: {outlabel(value); break;}
- case _GCHAR: {ol("MOV BX,AX"); ol("MOV AL,[BX]"); ol("CBW"); break;}
- case _GINT: {ol("MOV BX,AX"); ol("MOV AX,[BX]"); break;}
- case _LINT: {ot("MOV AX,"); outname(str+NAME); nl(); break;}
- case _LCHAR: {ot("MOV AL,"); outname(str+NAME); nl(); ol("CBW"); break;}
- case _GSTK: {ot("LEA AX,"); outdec(getint(str+OFFSET, OFFSIZE));
- outstr("[BP]"); nl(); break;}
- case _SCHAR: {ot("MOV "); outname(str+NAME); outstr(",AL"); nl(); break;}
- case _SINT: {ot("MOV "); outname(str+NAME); outstr(",AX"); nl(); break;}
- case _PINT: {ol("MOV [BX],AX"); break;}
- case _PCHAR: {ol("MOV [BX],AL"); break;}
- case _MOVE: {ol("MOV BX,AX"); break;}
- case _SWAP: {outswap(); break;}
- case _OFFSET:{ot("MOV AX,OFFSET "); outname(str+NAME); nl(); break;}
- case _STRING:{ot("MOV AX,OFFSET "); outlabel(litlab); outstr("+");
- outdec(value); nl(); break;}
- case _IMMED: {
- if(value) {ot("MOV AX,"); outdec(value);}
- else ot("XOR AX,AX");
- nl();
- break;
- }
- case _IMMED2: {
- if(value) {ot("MOV BX,"); outdec(value);}
- else ot("XOR BX,BX");
- nl();
- break;
- }
- case _COUNT: {
- if(value) {ot("MOV CL,"); outdec(value);}
- else ot("XOR CL,CL");
- nl();
- break;
- }
- case _PUSH: {ol("PUSH AX"); break;}
- case _POP: {ol("POP BX"); break;}
- case _SWAPSTK: {ol("POP BX"); ol("XCHG AX,BX"); ol("PUSH BX"); break;}
- case _SW: {outcall("__SWITCH"); break;}
- case _CALL: {ot("CALL "); outname(str+NAME); nl(); break;}
- case _FUNC: {ol("PUSH BP"); ol("MOV BP,SP"); break;}
- case _RET: {ol("POP BP"); ol("RET"); break;}
- case _CALLSTK: {ol("CALL AX"); break;}
- case _JUMP: {outjump(value); break;}
- case _TESTJUMP:{ol("OR AX,AX"); ol("JNZ $+5"); outjump(value); break;}
- case _DB: {ot(" DB "); break;}
- case _DBZERO: {ot(" DB "); outdec(value); outstr(" DUP(0)"); nl(); break;}
- case _DEFBYTE: {ot(" DB "); outdec(value); nl(); break;}
- case _DW: {ot(" DW "); break;}
- case _DWZERO: {ot(" DW "); outdec(value); outstr(" DUP(0)"); nl(); break;}
- case _DEFWORD: {ot(" DW "); outdec(value); nl(); break;}
- case _DEFLABEL:{ot(" DW "); outlabel(value); nl(); break;}
- case _MODSTK: {
- if(value) {ot("ADD SP,"); outdec(value); nl();}
- break;
- }
- case _DBL: {ol("ADD AX,AX"); break;}
- case _DBL2: {ol("ADD BX,BX"); break;}
- case _ADD: {ol("ADD AX,BX"); break;}
- case _SUB: {outswap(); ol("SUB AX,BX"); break;}
- case _MULT: {ol("IMUL BX"); break;}
- case _DIV: {outswap(); ol("CWD"); ol("IDIV BX"); break;}
- case _MOD: {outswap(); ol("CWD"); ol("IDIV BX"); ol("MOV AX,DX"); break;}
- case _OR: {ol("OR AX,BX"); break;}
- case _XOR: {ol("XOR AX,BX"); break;}
- case _AND: {ol("AND AX,BX"); break;}
- case _LNEG: {outcall("__LNEG"); break;}
- case _ASR: {ol("MOV CX,AX"); ol("MOV AX,BX"); ol("SAR AX,CL"); break;}
- case _ASL: {ol("MOV CX,AX"); ol("MOV AX,BX"); ol("SAL AX,CL"); break;}
- case _NEG: {ol("NEG AX"); break;}
- case _COM: {ol("NOT AX"); break;}
- case _INC: {while(1) {ol("INC AX"); if(--value < 1) break;} break;}
- case _DEC: {while(1) {ol("DEC AX"); if(--value < 1) break;} break;}
- case _EQ: {outcall("__EQ"); break;}
- case _EQ0: {ol("OR AX,AX"); ol("JZ $+5"); outjump(value); break;}
- case _NE: {outcall("__NE"); break;}
- case _NE0: {ol("OR AX,AX"); ol("JNZ $+5"); outjump(value); break;}
- case _LT: {outcall("__LT"); break;}
- case _LT0: {ol("OR AX,AX"); ol("JL $+5"); outjump(value); break;}
- case _LE: {outcall("__LE"); break;}
- case _LE0: {ol("OR AX,AX"); ol("JLE $+5"); outjump(value); break;}
- case _GT: {outcall("__GT"); break;}
- case _GT0: {ol("OR AX,AX"); ol("JG $+5"); outjump(value); break;}
- case _GE: {outcall("__GE"); break;}
- case _GE0: {ol("OR AX,AX"); ol("JGE $+5"); outjump(value); break;}
- case _ULT: {outcall("__ULT"); break;}
- case _ULT0: {outjump(value); break;}
- case _ULE: {outcall("__ULE"); break;}
- case _UGT: {outcall("__UGT"); break;}
- case _UGE: {outcall("__UGE"); break;}
- case _GLIO: {
- ot("LEA BX,"); outdec(value); outstr("[BP]"); nl();
- ol("MOV AX,[BX]");
- break;
- }
- case _GLCO: {
- ot("LEA BX,"); outdec(value); outstr("[BP]"); nl();
- ol("MOV AL,[BX]");
- ol("CBW");
- break;
- }
- case _GGIO1: {ot("MOV BX,OFFSET "); outname(str+NAME); break;}
- case _GGIO2: {
- if(value >= 0) outstr("+"); outdec(value); nl();
- ol("MOV AX,[BX]");
- break;
- }
- case _GGCO1: {ot("MOV BX,OFFSET "); outname(str+NAME); break;}
- case _GGCO2: {
- if(value >= 0) outstr("+"); outdec(value); nl();
- ol("MOV AL,[BX]");
- ol("CBW");
- break;
- }
- case _INT_I: {ot("ADD WORD PTR [BX],"); outdec(value); nl(); break;}
- case _INT_D: {ot("SUB WORD PTR [BX],"); outdec(value); nl(); break;}
- case _CHAR_I:{ot("ADD BYTE PTR [BX],"); outdec(value); nl(); break;}
- case _CHAR_D:{ot("SUB BYTE PTR [BX],"); outdec(value); nl(); break;}
- case _XXX_I1:{ot("ADD "); outname(str+NAME); break;}
- case _XXX_D1:{ot("SUB "); outname(str+NAME); break;}
- case _XXX_X2:{outstr(","); outdec(value); nl(); break;}
- case _FINT: {
- ot("LEA BX,"); outdec(getint(str+OFFSET, OFFSIZE)); outstr("[BP]"); nl();
- ol("MOV AX,[BX]");
- break;
- }
- case _FCHAR: {
- ot("LEA BX,"); outdec(getint(str+OFFSET, OFFSIZE)); outstr("[BP]"); nl();
- ol("MOV AL,[BX]");
- ol("CBW");
- break;
- }
- case _ADDI: {ot("ADD AX,"); outdec(value); nl(); break;}
- case _SUBI: {ot("SUB AX,"); outdec(value); nl(); break;}
-
- default: {error("bad pcode"); break;}
- }
- }
-
-